package cn.mw.cmdb.link.strategy.handler;

import cn.mw.cmdb.entity.InstanceInfoExtend;
import cn.mw.cmdb.link.entity.LinkHistoryTrendDto;
import cn.mw.cmdb.link.entity.MwLinkCountDto;
import cn.mw.cmdb.link.entity.MwLinkTargetIpInfo;
import cn.mw.cmdb.link.entity.MwNetWorkLinkDto;
import cn.mw.cmdb.link.enums.LinkDetectionWayEnum;
import cn.mw.cmdb.link.enums.LinkHistoryTypeEnum;
import cn.mw.cmdb.link.param.LinkParam;
import cn.mw.cmdb.link.strategy.LinkDetectionWayHandler;
import cn.mw.cmdb.param.zabbixResult.ItemApplication;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description 没有启用探测处理
 */
@Service
@Slf4j
public class LinkNotHaveEnableDetectionHandler extends LinkDetectionWayHandler {

    private final String MW_INTERFACE_STATUS = "MW_INTERFACE_STATUS";
    private final String INTERFACE_IN_DROP_RATE = "INTERFACE_IN_DROP_RATE";
    private final String INTERFACE_OUT_DROP_RATE = "INTERFACE_OUT_DROP_RATE";
    private final String NA = "N/A";

    @Override
    public LinkDetectionWayEnum handlerType() {
        return LinkDetectionWayEnum.NOT_HAVE;
    }

    @Override
    public void getLinkMonitorInfo(List<MwNetWorkLinkDto> dtos) throws Exception {
        List<String> itemNames = new ArrayList<>();
        //查询无检测的状态，响应时间，丢包率
        List<String> assetIds = new ArrayList<>();
        for (MwNetWorkLinkDto dto : dtos) {
            String takeValuePort = dto.getTakeValuePort();
            if(takeValuePort.equals(ROOT)){
                assetIds.add(dto.getSourceDeviceAsset());
                itemNames.add("["+dto.getSourceDevicePort()+"]"+MW_INTERFACE_STATUS);
                itemNames.add("["+dto.getSourceDevicePort()+"]"+INTERFACE_IN_DROP_RATE);
                itemNames.add("["+dto.getSourceDevicePort()+"]"+INTERFACE_OUT_DROP_RATE);
            }
            if(takeValuePort.equals(TARGET)){
                assetIds.add(dto.getTargetDeviceAsset());
                itemNames.add("["+dto.getTargetDevicePort()+"]"+MW_INTERFACE_STATUS);
                itemNames.add("["+dto.getTargetDevicePort()+"]"+INTERFACE_IN_DROP_RATE);
                itemNames.add("["+dto.getTargetDevicePort()+"]"+INTERFACE_OUT_DROP_RATE);
            }
        }
        //获取资产
        List<InstanceInfoExtend> assetInfo = getTargetDeviceAssetInfo(null, null,assetIds);
        log.info("LinkNotHaveEnableDetectionHandler{} getLinkMonitorInfo() assetInfo:::"+assetInfo);
        if(CollectionUtils.isEmpty(assetInfo)){return;}
        Map<Integer, List<String>> serverGroup = getHostIdGroup(assetInfo);
        //查询zabbix数据
        List<ItemApplication> itemApplications = getLinkZabbixMonitorInfo(serverGroup, itemNames);
        if(CollectionUtils.isEmpty(itemApplications)){return;}
        for (MwNetWorkLinkDto dto : dtos) {
            setNotEnableDetectionValueInfo(dto,itemApplications,assetInfo);
        }
        getLinkBandWidthUtilization(dtos);
    }

    @Override
    public List<MwLinkTargetIpInfo> getTargetIpInfo(LinkParam linkParam) throws Exception {
        return new ArrayList<>();
    }

    @Override
    public void handlerLinkData(MwNetWorkLinkDto netWorkLinkDto) throws Exception {

    }

    @Override
    public List<LinkHistoryTrendDto> getLinkHistoryTrend(MwNetWorkLinkDto netWorkLinkDto, LinkParam linkParam) throws Exception {
        List<LinkHistoryTrendDto> historyTrendDtos = new ArrayList<>();
        LinkHistoryTypeEnum historyTypeEnum = LinkHistoryTypeEnum.getHistoryTypeEnum(linkParam.getQueryType());
        switch (historyTypeEnum){
            case FLOW:
                historyTrendDtos = getHistoryTrendData(netWorkLinkDto, linkParam);
                break;
        }
        return historyTrendDtos;
    }

    private void setNotEnableDetectionValueInfo(MwNetWorkLinkDto linkDto,List<ItemApplication> itemApplications,List<InstanceInfoExtend> assetInfo){
        MwLinkCountDto countDto = new MwLinkCountDto();
        String takeValuePort = linkDto.getTakeValuePort();
        String port = null;
        InstanceInfoExtend instanceInfoExtend = null;
        if(takeValuePort.equals(ROOT)){
            port = linkDto.getSourceDevicePort();
            List<InstanceInfoExtend> anExtends = assetInfo.stream().filter(s -> s.getId().equals(linkDto.getSourceDeviceAsset())).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(anExtends)){
                instanceInfoExtend = anExtends.get(0);
            }
        }
        if(takeValuePort.equals(TARGET)){
            port = linkDto.getTargetDevicePort();
            List<InstanceInfoExtend> anExtends = assetInfo.stream().filter(s -> s.getId().equals(linkDto.getTargetDeviceAsset())).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(anExtends)){
                instanceInfoExtend = anExtends.get(0);
            }
        }
        if(instanceInfoExtend == null){return;}
        Integer monitorServerId = instanceInfoExtend.getMonitorServerId();
        String monitorTypeId = instanceInfoExtend.getMonitorTypeId();
        List<ItemApplication> applications = itemApplications.stream().filter(item -> (item.getHostid() + item.getServerId()).equals(monitorTypeId + monitorServerId)).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(applications)){return;}
        for (ItemApplication itemApplication : applications){
            String name = itemApplication.getName();
            String lastvalue = itemApplication.getLastvalue();
            if(name.contains("["+port+"]"+MW_INTERFACE_STATUS)){//设置状态
                linkDto.setStatus(Double.parseDouble(lastvalue) == 1?NORMAL:ABNORMAL);
            }
            if(name.contains("["+port+"]"+INTERFACE_IN_DROP_RATE)){
                countDto.setInDropRate(Double.parseDouble(lastvalue));
            }
            if(name.contains("["+port+"]"+INTERFACE_OUT_DROP_RATE)){
                countDto.setOutDropRate(Double.parseDouble(lastvalue));
            }
        }
        //计算丢包率
        linkDto.setLossRate(new BigDecimal((countDto.getInDropRate()+countDto.getOutDropRate()) / 2).setScale(2,BigDecimal.ROUND_HALF_UP).toString()+LOSS_RATE_UNIT);
        linkDto.setResponseTime(NA);
    }
}
